/**
 * 网络请求封装
 * @description api模块管理，loading配置，请求拦截，错误处理
 */

import Request from "luch-request";
import { baseUrl } from "@/utils/util.js";


// 请求选项默认值
const options = {
    // 显示操作成功消息 默认不显示
    showSuccess: false,
    // 成功提醒 默认使用后端返回值
    successMsg: "",
    // 显示失败消息 默认显示
    showError: true,
    // 失败提醒 默认使用后端返回信息
    errorMsg: "",
    // 显示请求时loading模态框 默认显示
    showLoading: true,
    // loading提醒文字
    loadingMsg: "加载中",
    // 需要授权才能请求 默认放开
    auth: false,
};

// Loading全局实例
let LoadingInstance = {
    target: null,
    count: 0,
};

/**
 * 关闭loading
 */
function closeLoading() {
    if (LoadingInstance.count > 0) LoadingInstance.count--;
    if (LoadingInstance.count === 0) uni.hideLoading();
}

/**
 * @description 请求基础配置
 */
const http = new Request({
    baseURL: baseUrl,
    timeout: 8000,
    method: "GET",
    header: {
        platform: "uniapp",
        "tenant-id": "1",
    },
    // #ifdef APP-PLUS
    sslVerify: false,
    // #endif
    // #ifdef H5
    withCredentials: false,
    // #endif
    custom: options,
});

/**
 * @description 请求拦截器
 */
http.interceptors.request.use(
    (config) => {
        // 处理授权
        if (config?.custom?.auth && !getToken()) {
            uni.showToast({
                title: "请先登录",
                icon: "none",
            });
            // 可以在这里添加跳转到登录页的逻辑
            return Promise.reject();
        }

        // 处理loading
        if (config.custom.showLoading) {
            LoadingInstance.count++;
            LoadingInstance.count === 1 &&
                uni.showLoading({
                    title: config.custom.loadingMsg,
                    mask: true,
                    fail: () => {
                        uni.hideLoading();
                    },
                });
        }

        // 添加token
        const token = getToken();

        if (token) {
            config.header["Authorization"] = "Bearer " + token;
        }

        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

/**
 * @description 响应拦截器
 */
http.interceptors.response.use(
    (response) => {
        // 关闭loading
        response?.config?.custom?.showLoading && closeLoading();
        console.log('response:', response);
        if (response.data.code === 401) {
            handleUnauthorized();
        }
        
        // 返回数据，不做统一处理，由各接口自行处理不同状态码
        return response.data;
    },
    (error) => {
        console.log('网络请求出错了，处理一下')
        console.log(error.statusCode)
        let errorMessage = "网络请求出错";

        if (error !== undefined) {
            if (error.statusCode) {
                switch (error.statusCode) {
                    case 400:
                        errorMessage = "请求错误";
                        break;
                    case 401:
                        errorMessage = "未授权，请登录";
                        handleUnauthorized();
                        break;
                    case 403:
                        errorMessage = "拒绝访问";
                        break;
                    case 404:
                        errorMessage = "请求地址不存在";
                        break;
                    case 408:
                        errorMessage = "请求超时";
                        break;
                    case 500:
                        errorMessage = "服务器内部错误";
                        break;
                    case 501:
                        errorMessage = "服务未实现";
                        break;
                    case 502:
                        errorMessage = "网络错误";
                        break;
                    case 503:
                        errorMessage = "服务不可用";
                        break;
                    case 504:
                        errorMessage = "网络超时";
                        break;
                    default:
                        errorMessage = `未知错误(${error.statusCode})`;
                }
            }

            if (error.errMsg && error.errMsg.includes("timeout")) {
                errorMessage = "请求超时";
            }

            // #ifdef H5
            if (error.errMsg && error.errMsg.includes("Network")) {
                errorMessage = window.navigator.onLine
                    ? "服务器异常"
                    : "请检查您的网络连接";
            }
            // #endif
        }

        // 关闭loading
        if (error && error.config) {
            if (error.config.custom.showError) {
                uni.showToast({
                    title: error.data?.msg || errorMessage,
                    icon: "none",
                    mask: true,
                });
            }
            error.config.custom.showLoading && closeLoading();
        }

        return Promise.reject(error);
    }
);

/**
 * 处理未授权
 */
function handleUnauthorized() {
    // 清除token
    uni.removeStorageSync("token");

    // 提示用户
    uni.showToast({
        title: "登录已过期，请重新登录",
        icon: "none",
    });

    // 可以在这里添加跳转到登录页的逻辑
    uni.navigateTo({
        url: '/pages/login/login',
    });
}

/**
 * 获取token
 */
function getToken() {
    return uni.getStorageSync("token");
}

/**
 * GET请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 请求配置
 */
const get = (url, data = {}, options = {}) => {
    return http.get(url, {
        params: data,
        custom: { ...http.config.custom, ...options },
    });
};

/**
 * POST请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 请求配置
 */
const post = (url, data = {}, options = {}) => {
    return http.post(url, data, {
        custom: { ...http.config.custom, ...options },
    });
};

/**
 * PUT请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 请求配置
 */
const put = (url, data = {}, options = {}) => {
    return http.put(url, data, {
        custom: { ...http.config.custom, ...options },
    });
};

/**
 * DELETE请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {Object} options 请求配置
 */
const del = (url, data = {}, options = {}) => {
    return http.delete(url, {
        data,
        custom: { ...http.config.custom, ...options },
    });
};

// 导出请求方法
export default {
    get,
    post,
    put,
    delete: del,
};
